package cn.myapps.msg.sender;

import cn.myapps.msg.PushControl;
import cn.myapps.msg.enums.MsgStatusEnum;
import cn.myapps.msg.maker.WxCpMsgMaker;
import cn.myapps.msg.vo.MsgCommon;
import cn.myapps.msg.vo.SendResult;
import cn.myapps.msg.wx.entity.MsgWxCp;
import cn.myapps.msg.wx.entity.WxCpApp;
import cn.myapps.msg.wx.service.IMsgWxCpService;
import cn.myapps.msg.wx.service.IWxCpAppService;
import cn.myapps.msg.wx.vo.DefaultWxCpTemplate;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceApacheHttpClientImpl;
import me.chanjar.weixin.cp.bean.WxCpMessage;
import me.chanjar.weixin.cp.bean.WxCpMessageSendResult;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jeecg.common.util.SpringContextUtils;

/**
 * @Description: 微信企业号模板消息发送器
 * @Author: nicholas
 * @Date:   2020-06-19
 * @Version: V1.0
 */
@Slf4j
public class WxCpMsgSender implements IMsgSender {
    private WxCpMsgMaker wxCpMsgMaker;
    private static IWxCpAppService wxCpAppService;
    private static IMsgWxCpService msgWxCpService;

    private WxCpDefaultConfigImpl wxCpConfigStorage;
    private WxCpService wxCpService;

    public WxCpMsgSender() {
        wxCpMsgMaker = new WxCpMsgMaker();
        wxCpAppService = SpringContextUtils.getBean(IWxCpAppService.class);
        msgWxCpService = SpringContextUtils.getBean(IMsgWxCpService.class);
    }

    @Override
    public SendResult send(MsgCommon msg) {
        SendResult sendResult = new SendResult();


        wxCpMsgMaker.prepare(new DefaultWxCpTemplate());
        // 获取企业微信配置
        WxCpApp wxCpApp = wxCpAppService.findByAppName(msg.getFrom());

        MsgWxCp msgWxCp = wxCpMsgMaker.makeMsg(msg);
        msgWxCp.setAgentId(wxCpApp.getAgentId());

        try {
            if (PushControl.dryRun) {
                sendResult.setSuccess(true);
                return sendResult;
            } else {
                WxCpMessageSendResult wxCpMessageSendResult = getWxCpService(wxCpApp).messageSend(wxCpMsgMaker.toWxCpMessage(msgWxCp));
                if (wxCpMessageSendResult.getErrCode() != 0 || StringUtils.isNoneEmpty(wxCpMessageSendResult.getInvalidUser())) {
                    log.error(wxCpMessageSendResult.toString());

                    handleError(sendResult, msgWxCp, wxCpMessageSendResult.toString());

                    return sendResult;
                } else {
                    msgWxCp.setMsgStatus(MsgStatusEnum.SENED.getCode());
                }
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));

            handleError(sendResult, msgWxCp, ExceptionUtils.getStackTrace(e));

            return sendResult;
        }

        msgWxCpService.save(msgWxCp);

        sendResult.setSuccess(true);
        return sendResult;
    }

    @Override
    public SendResult sendByTemplate(MsgCommon msg) {
        throw new UnsupportedOperationException("不支持模板发送模式");
    }

    @Override
    public SendResult asyncSend(MsgCommon msg) {
        throw new UnsupportedOperationException("不支持异步发送模式");
    }

    /**
     * 微信企业号配置
     *
     * @return WxCpConfigStorage
     */
    private static WxCpDefaultConfigImpl wxCpConfigStorage(WxCpApp wxCpApp) {
        WxCpDefaultConfigImpl configStorage = new WxCpDefaultConfigImpl();

        if (wxCpApp != null) {
            configStorage.setCorpSecret(wxCpApp.getSecret());
        }
        configStorage.setAgentId(Integer.valueOf(wxCpApp.getAgentId()));
        configStorage.setCorpId(wxCpApp.getCorpId());
//        if (App.config.isMpUseProxy()) {
//            configStorage.setHttpProxyHost(App.config.getMpProxyHost());
//            configStorage.setHttpProxyPort(Integer.parseInt(App.config.getMpProxyPort()));
//            configStorage.setHttpProxyUsername(App.config.getMpProxyUserName());
//            configStorage.setHttpProxyPassword(App.config.getMpProxyPassword());
//        }
        DefaultApacheHttpClientBuilder clientBuilder = DefaultApacheHttpClientBuilder.get();
        //从连接池获取链接的超时时间(单位ms)
        clientBuilder.setConnectionRequestTimeout(10000);
        //建立链接的超时时间(单位ms)
        clientBuilder.setConnectionTimeout(5000);
        //连接池socket超时时间(单位ms)
        clientBuilder.setSoTimeout(5000);
        //空闲链接的超时时间(单位ms)
        clientBuilder.setIdleConnTimeout(60000);
        //空闲链接的检测周期(单位ms)
        clientBuilder.setCheckWaitTime(60000);
        //每路最大连接数
        clientBuilder.setMaxConnPerHost(wxCpApp.getMaxConnPool());
        //连接池最大连接数
        clientBuilder.setMaxTotalConn(wxCpApp.getMaxConnPool() * 2);
        //HttpClient请求时使用的User Agent
//        clientBuilder.setUserAgent(..)
        configStorage.setApacheHttpClientBuilder(clientBuilder);
        return configStorage;
    }

    /**
     * 获取微信企业号工具服务
     *
     * @return WxCpService
     */
    public WxCpService getWxCpService(WxCpApp wxCpApp) {
        if (wxCpConfigStorage == null) {
            synchronized (this) {
                if (wxCpConfigStorage == null) {
                    wxCpConfigStorage = wxCpConfigStorage(wxCpApp);
                }
            }
        }
        if (wxCpService == null && wxCpConfigStorage != null) {
            synchronized (this) {
                if (wxCpService == null && wxCpConfigStorage != null) {
                    wxCpService = new WxCpServiceApacheHttpClientImpl();
                    wxCpService.setWxCpConfigStorage(wxCpConfigStorage);
                }
            }
        }

        return wxCpService;
    }

    private String getAgentId(MsgCommon msg){
        if (msg.getOtherParams().containsKey("agentId")){
            return (String) msg.getOtherParams().get("agentId");
        }

        return null;
    }

    /**
     * 处理异常
     *
     * @param sendResult
     * @param msgWxCp
     * @param error
     */
    private void handleError(SendResult sendResult, MsgWxCp msgWxCp, String error){
        sendResult.setSuccess(false);
        sendResult.setInfo(error);
        log.error(error);

        msgWxCp.setMsgStatus(MsgStatusEnum.ERROR.getCode());
        msgWxCp.setError(error);
    }
}
